package com.gurumades.jsonform.server.forms.dispatch.handlers;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.persistence.Lob;

import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ObjectNode;

import net.customware.gwt.dispatch.server.ActionHandler;
import net.customware.gwt.dispatch.server.ExecutionContext;
import net.customware.gwt.dispatch.shared.DispatchException;

import com.gurumades.jsonform.client.presenter.FormItemError;
import com.gurumades.jsonform.server.forms.dispatch.DispatchUtil;
import com.gurumades.jsonform.server.forms.dispatch.FormPreprocessHelp;
import com.gurumades.jsonform.server.forms.dispatch.FormProvider;
import com.gurumades.jsonform.server.forms.dispatch.SubmitHelper;
import com.gurumades.jsonform.shared.dispatch.SubmitFormAction;
import com.gurumades.jsonform.shared.dispatch.SubmitFormResult;

public class SubmitFormHandler implements ActionHandler<SubmitFormAction, SubmitFormResult>{
	private JsonParser parser;
	
	public SubmitFormHandler() {
		
	}
	
	@Override
	public Class<SubmitFormAction> getActionType() {
		return SubmitFormAction.class;
	}
	
	@SuppressWarnings({ "serial", "unchecked", "rawtypes" })
	@Override
	public SubmitFormResult execute(SubmitFormAction action, ExecutionContext context)
			throws DispatchException {
		FormProvider provider = DispatchUtil.getFormProviders().get(action.getFormID());
		
		if (provider == null) {
			throw new DispatchException("No such form found") {};
		}
		
		String form = provider.getForm(action.getFormID());
		
		try {
			JsonFactory factory = new ObjectMapper().getJsonFactory();
			parser = factory.createJsonParser(new StringReader(form));
			JsonNode jsonForm = parser.readValueAsTree();
			parser.close();
			
			ArrayList<String> object = action.getJsonEncodedObject();
			Map<String, JsonNode> lines = new HashMap<String, JsonNode>();
			
			for (String string : object) {
				parser = factory.createJsonParser(new StringReader(string));
				JsonNode item = parser.readValueAsTree();
				
				if (item.isObject()) {
					ObjectNode itemObject = (ObjectNode)item;
					lines.put(itemObject.path("id").getTextValue(), itemObject);
				}
				
				parser.close();
			}
			
			Long buildID = 0L;
			
			try{
				buildID = Long.parseLong(lines.get("buildID").get("buildID").getTextValue());
			}catch (Exception e) {
				// TODO: handle exception
			}
			jsonForm = DispatchUtil.preprocessForm(action.getFormID(), jsonForm, false, buildID);
			
			HashMap<String, FormItemError> errors = DispatchUtil.validateForm(action.getFormID(), jsonForm, (HashMap) lines);
			if (errors.size() > 0) {
				SubmitFormResult returnVal = new SubmitFormResult(action.getFormID(), false);
				returnVal.setErrors(new ArrayList<FormItemError>(errors.values()));
				
				return returnVal;
			}
			
			SubmitHelper helper = DispatchUtil.submitForm(action.getFormID(), jsonForm, lines);
			SubmitFormResult returnVal = new SubmitFormResult(action.getFormID(), true);
			if (helper != null) {
				returnVal.setContext(helper.getReturnVals());
			}
			
			return returnVal;
			
		} catch (JsonParseException e) {
			e.printStackTrace();
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return null;
	}

	@Override
	public void rollback(SubmitFormAction action, SubmitFormResult result,
			ExecutionContext context) throws DispatchException {
		
	}

}
